const MSG_HEADER_LEN = 20;//消息头长度
const MSG_MAX_SIZE = 1073741824;//消息最大长度1G
const MSG_HEADER_FLAG = 0x20110908;
const MSG_RESP_DIFF = 0x10000000;

// struct ssNetMsgHead
// {
// 	u32		m_dwTcpFlag;	// 消息头标志
// 	u32		m_dwLen;		// 消息体长度，包括消息包头
// 	u32		m_dwMsgID;		// 消息编号（请求方产生，响应方和通知类消息由server产生）

// 	u32		m_dwSessionID;	// 连接ID，网关使用
// 	u32		m_dwParam1;		// 参数1
// };

class SocketPackage {
	static MSG_HEADER_LEN = MSG_HEADER_LEN;
	static MSG_MAX_SIZE = MSG_MAX_SIZE;
	static MSG_HEADER_FLAG = MSG_HEADER_FLAG;
	static MSG_RESP_DIFF = MSG_RESP_DIFF;

    constructor(callback){
		this.buffer = null;
		this.callback = callback;
		this.socket = null;
	}
    onReceive(socket,data){
        if (this.buffer) {
            this.buffer = Buffer.concat([this.buffer,data]);
        } else {
            this.buffer = Buffer.from(data);
        }
		this.socket = socket;
		if (this._parseData()) {
			this.buffer = null;
		}
    }
	_parseData(){
		if (this.buffer.length>0) {
			let len = this.buffer.length;
			let readSize = 0;
			let runCt = 0;
			while (runCt++ < 200)
			{
				if (len < MSG_HEADER_LEN || len > MSG_MAX_SIZE) {
					return true;
				}
				//check msg
				let dwTcpFlag = this.buffer.readUInt32LE(0);
				let dwLen = this.buffer.readUInt32LE(4);
				// let dwMsgID = this.buffer.readUInt32BE(8);
				if (dwTcpFlag != MSG_HEADER_FLAG || dwLen > MSG_MAX_SIZE || dwLen < MSG_HEADER_LEN)
				{
					return true;
				}
				if (len < dwLen)
				{
					this.buffer = this.buffer.slice(readSize);
					break;
				}
				if (this.callback)
				{
					let pack = Buffer.allocUnsafe(dwLen);
					this.buffer.copy(pack,0,0,dwLen);
					this.callback(this.socket, pack);
				}
				readSize += dwLen;
				len -= dwLen;
				if (len<=0) {
					this.buffer = null;
				} else {
					this.buffer = this.buffer.slice(dwLen);
				}
			}
		}
		return false;
	}
	static serializePackage(msgID, data){
		let dataLen = data?data.length:0;
		let head = Buffer.alloc(MSG_HEADER_LEN);
		head.writeInt32LE(MSG_HEADER_FLAG,0);
		head.writeUInt32LE(MSG_HEADER_LEN+dataLen,4);
		head.writeUInt32LE(msgID,8);
		if (data) {
			return Buffer.concat([head,data]);
		} else {
			return head;
		}
	}
	static unserializePackage(data){
		// let tcpFlag = data.readUInt32LE(0);
		let len = data.readUInt32LE(4);
		let msgID = data.readUInt32LE(8);
		return {len:len, msgID:msgID, data:len==MSG_HEADER_LEN?null:data.slice(MSG_HEADER_LEN)};
	}
	static serializeRpcPackage(sn, msgID, data){
		let dataLen = data?data.length:0;
		let head = Buffer.alloc(MSG_HEADER_LEN+4);
		head.writeInt32LE(MSG_HEADER_FLAG,0);
		head.writeUInt32LE(MSG_HEADER_LEN+4+dataLen,4);
		head.writeUInt32LE(msgID,8);
		head.writeUInt32LE(sn,MSG_HEADER_LEN);
		if (data) {
			return Buffer.concat([head,data]);
		} else {
			return head;
		}
	}
	static unserializeRpcPackage(data){
		// let tcpFlag = data.readUInt32LE(0);
		let len = data.readUInt32LE(4);
		let msgID = data.readUInt32LE(8);
		let sn = data.readUInt32LE(MSG_HEADER_LEN);
		return {len:len, msgID:msgID, sn:sn, data:len==(MSG_HEADER_LEN+4)?null:data.slice(MSG_HEADER_LEN+4)};
	}
}

Object.freeze(SocketPackage.MSG_HEADER_LEN);
Object.freeze(SocketPackage.MSG_MAX_SIZE);
Object.freeze(SocketPackage.MSG_HEADER_FLAG);
Object.freeze(SocketPackage.MSG_RESP_DIFF);

module.exports = SocketPackage;
